package com.coderman.common.starter.logparam.processor;

import com.alibaba.fastjson.JSON;
import com.coderman.common.starter.logparam.annotations.InnerBusLog;
import com.coderman.common.starter.logparam.annotations.RequestLogic;
import com.coderman.common.starter.logparam.beans.InnerBusLogBean;
import com.coderman.common.starter.logparam.beans.RequestLogicBean;
import com.coderman.common.starter.logparam.context.InnerBusLogicContext;
import com.coderman.common.starter.logparam.context.RequestBusLogicContext;
import com.coderman.common.starter.logparam.exceptions.NotSupportValidTypeException;
import com.coderman.common.starter.logparam.service.paramvalid.ValidParamHelperService;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Description: spring bean后置处理器,扫描元数据
 * date020/10/14
 *
 * @author fanchunai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Component
public class RequestLogicBeanProcessor implements BeanPostProcessor {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 类路径容器
     */
    private Map<String, String> map = new HashMap<>();

    @Resource
    private RequestBusLogicContext requestBusLogicContext;


    @Resource
    private InnerBusLogicContext innerBusLogicContext;

    @Resource
    private ValidParamHelperService validParamHelperService;


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        String clazzPath = bean.getClass().getCanonicalName();
        map.put(beanName, clazzPath);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Method[] methods = null;

        String classPath = map.get(beanName);
        if (StringUtils.isNotEmpty(classPath)) {
            Class<?> tClass = null;
            try {
                tClass = Class.forName(classPath);
            } catch (ClassNotFoundException e) {
                logger.warn("class not found.");
            }
            if (tClass != null) {
                methods = tClass.getDeclaredMethods();
            }
        }
        try {
            if (methods != null) {
                for (Method method : methods) {
                    RequestLogic baseBusLogic = AnnotationUtils.findAnnotation(method, RequestLogic.class);
                    if (null != baseBusLogic) {
                        //插入到上下文中
                        RequestLogicBean baseBusLogicBean = new RequestLogicBean();
                        // String clazzName = classPath.substring(classPath.lastIndexOf(".") + 1);
                        String key = getKey(classPath, method);
                        baseBusLogicBean.setExeTime(baseBusLogic.exeTime());
                        baseBusLogicBean.setParamNotNull(baseBusLogic.paramNotNull());
                        baseBusLogicBean.setLogInParam(baseBusLogic.logInParam());
                        baseBusLogicBean.setLogOutParam(baseBusLogic.logOutParam());
                        baseBusLogicBean.setValidModel(baseBusLogic.validModel());
                        baseBusLogicBean.setErrorReturnModel(baseBusLogic.errReturnModel().getModel());
                        logger.info("baseBusLogicBean = " + JSON.toJSONString(baseBusLogicBean) + ",BaseBusLogic key = " + key);

                        //验证错误返回类型
                        validParamHelperService.checkReturnModel(baseBusLogic.errReturnModel().getModel());
                        //验证表达式
                        validParamHelperService.checkValidValue(baseBusLogic.validModel());
                        requestBusLogicContext.getRequestLogicMap().put(key.hashCode(), baseBusLogicBean);
                    }

                    //处理内部日志逻辑
                    InnerBusLog innerBusLog = AnnotationUtils.findAnnotation(method, InnerBusLog.class);
                    if (null != innerBusLog) {
                        //插入到上下文中
                        InnerBusLogBean innerBusLogBean = new InnerBusLogBean();

                        String key = getKey(classPath, method);
                        logger.info("innerBusLogBean = " + JSON.toJSONString(innerBusLogBean) + ",inner BusLog key = " + key);
                        innerBusLogBean.setExeTime(innerBusLog.exeTime());
                        innerBusLogBean.setLogInParam(innerBusLog.logInParam());
                        innerBusLogBean.setLogOutParam(innerBusLog.logOutParam());
                        innerBusLogicContext.getInnerBaseBusLogMap().put(key.hashCode(), innerBusLogBean);
                    }
                }
            }

        } catch (NotSupportValidTypeException e) {
            logger.error("postProcessBeforeInitialization NotSupportValidType error", e);
        }

        return bean;
    }

    /**
     * 获取key
     *
     * @param classPath
     * @param method
     * @return
     */
    private String getKey(String classPath, Method method) {
        StringBuilder builder = new StringBuilder();
        builder.append(classPath + "." + method.getName() + "(");
        Class<?>[] clazzParamType = method.getParameterTypes();
        if (clazzParamType != null) {
            for (Class<?> clazz : clazzParamType) {
                String typeName = clazz.getSimpleName();
                builder.append(typeName + ",");
            }
        }
        String key = builder.toString();
        if (key.endsWith("(")) {
            return builder.append(")").toString();
        }
        return key.substring(0, key.length() - 1) + ")";
    }
}
